use std::{cell::UnsafeCell , fmt::{self,Display} , mem, ops::Deref} ;
use std::mem::MaybeUninit;



/// rocell 一个泛型容器
/// 先放一块未初始化的内存 程序运行到的时候再写入一次，之后只能读取不可以修改
pub struct RoCell<T>{
	inner : UnsafeCell<MaybeUninit<T>> , 
	#[cfg(debug_assertions)]
	initialized: UnsafeCell<bool> , 
}

unsafe impl<T> Sync for RoCell<T>{}

impl<T> RoCell<T> {
	/* ------------  创建  ------------------*/
	#[inline]
	pub const fn new() -> Self {
		Self{
			inner: UnsafeCell::new(MaybeUninit::uninit()),  // 空cell  没有初始化
			#[cfg(debug_assertions)]
			initialized : UnsafeCell::new(false) ,
		}
	}
	#[inline]
	pub const fn new_const(value:T)->Self{
		Self{
			inner : UnsafeCell::new(MaybeUninit::new(value)) ,   // 编译器就带初始值
			#[cfg(debug_assertions)]
			initialized : UnsafeCell::new(true ) , 
		} 
	}
	/* ------------  写入  ------------------*/
	#[inline]
	pub fn init(&self,value:T) {  // 运行时写入一次 
		unsafe {
			#[cfg(debug_assertions)]
			assert!(!self.initialized.get().replace(true)); 
			*self.inner.get() = MaybeUninit::new(value);  
		}
	}
	#[inline] 
	pub fn with<F>(&self, f:F)
	where 
		F:FnOnce() -> T ,
	{
		self.init(f()) ; // 按需惰性计算后写入
	}

	/* ------------  取出重置  ------------------*/
	#[inline]
	pub fn drop(&self) -> T{
		unsafe {
			#[cfg(debug_assertions)]
			assert!(!self.initialized.get().replace(false));
			self.inner.get().replace(MaybeUninit::uninit()).assume_init()
		}
	}
	
}





/* ------------  只读访问接口  ------------------*/
impl<T> Deref for RoCell<T> {
	type Target = T; 
	fn deref(&self) -> &Self::Target {
		unsafe{
			#[cfg(debug_assertions)]
			assert!(*self.initialized.get()) ;
			(*self.inner.get()).assume_init_ref() 
		}
	}
}



/* ------------  辅助实现  ------------------*/
impl<T> Default for RoCell<T>{
	fn default() -> Self {
		Self::new()
	}
}

impl<T> Display for RoCell<T>
where 
	T:Display
{
	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result{
		self.deref().fmt(f)
	}
}


// 内联测试 直接在实现文件中使用#[cfg(test)]模块编写测试代码
// 集成测试 在tests目录下创建单独的测试文件
// 对于核心数据结构  推荐使用内联测试  更接近实现代码利于维护
/* --------------  内联测试 ------------------ */ 
#[cfg(test)]
mod tests {
	use super::*;

	#[test]
	fn test_new_and_init() {
		let cell = RoCell::<i32>::new();
		assert_eq!(unsafe { *cell.initialized.get() }, false); // 确保未初始化
		cell.init(42);
		assert_eq!(unsafe { *cell.initialized.get() }, true); // 确保已初始化
		assert_eq!(*cell, 42); // 验证值是否正确
	}

	#[test]
	fn test_new_const() {
		let cell = RoCell::new_const(100);
		assert_eq!(unsafe { *cell.initialized.get() }, true); // 确保已初始化
		assert_eq!(*cell, 100); // 验证值是否正确
	}

	#[test]
	fn test_with_lazy_initialization() {
		let cell = RoCell::<String>::new();
		cell.with(|| "lazy initialized".to_string());
		assert_eq!(*cell, "lazy initialized"); // 验证惰性初始化是否正确
	}
	
	#[test]
	#[should_panic(expected = "assertion failed")]
	fn test_double_init_should_panic() {
		let cell = RoCell::<i32>::new();
		cell.init(10);
		cell.init(20); // 第二次初始化应该触发断言失败
	}

	#[test]
	#[should_panic(expected = "assertion failed")]
	fn test_deref_uninitialized_should_panic() {
		let cell = RoCell::<i32>::new();
		let _value = *cell; // 访问未初始化的值应该触发断言失败
	}
	
}
